﻿using System;

namespace WindowsFormsApplication1
{
    public class TestClass
    {
        public static int CAN_CHANGE = 0; 

        /// <summary>
        /// 定义一个类中的常量，不允许修改
        /// </summary>
        public const double PI = 3.1415926;

        /// <summary>
        /// 定义了一个只读静态变量，只能在静态构造时对其进行改变，其他地方为只读
        /// </summary>
        public static readonly string COLOR = "#383838";

        /// <summary>
        /// 定义了一个只读变量，只能在构造时对其进行改变，其他地方为只读
        /// </summary>
        private readonly string GULANGYU = "XM";

        /// <summary>
        /// 定义个私有常量
        /// </summary>
        private const int TTYPE = 10;

        /// <summary>
        /// 私有的字符串，不能在外部修改
        /// </summary>
        private string s_now_str = "这是私有的字符串";

        /// <summary>
        /// 当前的INT
        /// </summary>
        private int s_now_int = 0;

        /// <summary>
        /// 未初始化的字符串
        /// </summary>
        private string s_now_pri;

        /// <summary>
        /// 构造函数
        /// </summary>
        public TestClass()
        {
            this.s_now_pri = "在构造时被赋值了";
            Console.WriteLine("TestClass初始化1");
            this.GULANGYU = "XIAMEN";
            //这里会出错，因为COLOR是静态只读变量，无法在普通构造进行修改
            //COLOR = "#838383";
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~TestClass()
        {
            Console.WriteLine("TestClass被销毁了");
        }

        /// <summary>
        /// 带参数的构造函数
        /// </summary>
        /// <param name="p_pri">要赋值的当前类私有字段</param>
        public TestClass(string p_pri)
        {
            this.s_now_pri = p_pri;
            Console.WriteLine("TestClass初始化2");
        }

        /// <summary>
        /// 带参数的构造函数2,未给私有string赋值
        /// </summary>
        /// <param name="p_int">当前的INT</param>
        public TestClass(int p_int)
        {
            this.s_now_int = p_int;
            Console.WriteLine("TestClass初始化3");
        }

        /// <summary>
        /// 获取当前的私有string字段，有可能因为未赋值而出错
        /// </summary>
        /// <returns>当前的私有string字段</returns>
        public string getNowPri()
        {
            //这里会出错，因为GULANGYU是只读的，不允许修改
            //this.GULANGYU = "QUANZHOU";
            return this.s_now_pri;
        }

        /// <summary>
        /// 定义一个只读属性，当前Pri
        /// </summary>
        public string Pri
        {
            get
            {
                return this.s_now_pri;
            }
        }

        /// <summary>
        /// 定义一个读写属性，当前Str
        /// </summary>
        public string Str
        {
            get
            {
                return this.s_now_str;
            }
            set
            {
                this.s_now_str = value;
            }
        }

        /// <summary>
        /// 建立一个一维类索引器
        /// </summary>
        /// <param name="index">数组下标</param>
        /// <returns></returns>
        public int this[int index]
        {
            get
            {
                int t_out;
                switch (index)
                {
                    case 0 :
                        t_out = this.GetHashCode();
                        break;
                    case 1 :
                        t_out = this.getTtype();
                        break;
                    case 2 :
                        t_out = this.s_now_int;
                        break;
                    case 3 :
                        t_out = CAN_CHANGE;
                        break;
                    case 4 :
                        t_out = 400;
                        break;
                    default :
                        t_out = 1000;
                        break;
                }
                return t_out;
            }

            set
            {
                if (index == 0)
                {
                    this.s_now_int = value;
                }
                else
                {
                    CAN_CHANGE = value;
                }
            }
        }

        /// <summary>
        /// 当前类可以获取当前类的所有字段
        /// </summary>
        /// <returns></returns>
        public string getNowStr()
        {
            return this.s_now_str;
        }

        /// <summary>
        /// 简单测试函数
        /// </summary>
        /// <param name="p_int">当前INT</param>
        public void changeNow(int p_int)
        {
            this.s_now_int = p_int;
            Console.WriteLine("进行了changeNow");
        }

        /// <summary>
        /// 测试参数的类型及重载
        /// </summary>
        /// <param name="p_int">普通参数，修改当前INT</param>
        /// <param name="p_chg">REF参数，需要初始化</param>
        /// <param name="p_shi">OUT参数，不需要初始化，实际上初始化也没用，会被函数覆盖</param>
        public void changeNow(int p_int, ref int p_chg, out int p_shi)
        {
            this.s_now_int = p_int;
            p_chg = p_chg + this.s_now_int;
            p_shi = p_chg;
            Console.WriteLine("进行了changeNow");
            Console.WriteLine("当前的REF是{0}", p_chg);
            Console.WriteLine("当前的OUT是{0}", p_shi);
        }

        /// <summary>
        /// 获取当前类的PI
        /// </summary>
        /// <returns>PI值</returns>
        public double getPI()
        {
            return PI;
        }

        /// <summary>
        /// 获取当前TTYPE
        /// </summary>
        /// <returns>TTYPE值</returns>
        public int getTtype()
        {
            return TTYPE;
        }

        /// <summary>
        /// 测试不同返回类型的同名方法而产生的错误
        /// </summary>
        /// <returns></returns>
        public bool getTtype2()
        {
            return false;
        }

        /// <summary>
        /// 声明一个委托，用于获取两个数的其中一个。委托是静态定义，不能用this访问。
        /// </summary>
        /// <param name="p_one">第一个数</param>
        /// <param name="p_two">第二个数</param>
        /// <returns></returns>
        public delegate int getSome(int p_one, int p_two);

        /// <summary>
        /// 这是一个符合getSome委托的函数定义
        /// </summary>
        /// <param name="p_one">第一个数</param>
        /// <param name="p_two">第二个数</param>
        /// <returns></returns>
        public int getTwo(int p_one, int p_two)
        {
            return p_one + p_two;
        }

        /// <summary>
        /// 实例化了getSome委托，进行了实际操作
        /// </summary>
        /// <param name="p_one">第一个数</param>
        /// <param name="p_two">第二个数</param>
        /// <returns></returns>
        public int getFrom(int p_one, int p_two)
        {
            getSome gtwo = this.getTwo;
            return gtwo(p_one, p_two);
        }

        /// <summary>
        /// 委托自定义方法参数
        /// </summary>
        /// <param name="doget">符合getSome定义的函数名</param>
        /// <param name="p_one">第一个参数</param>
        /// <param name="p_two">第二个参数</param>
        /// <returns></returns>
        public int getFrom(getSome doget, int p_one, int p_two)
        {
            return doget(p_one, p_two);
        }

        /// <summary>
        /// 定义一个私有委托
        /// </summary>
        /// <param name="p_name"></param>
        /// <param name="p_some"></param>
        private delegate void say(string p_name, string p_some);

        /// <summary>
        /// 符合委托say的方法定义
        /// </summary>
        /// <param name="p_name"></param>
        /// <param name="p_some"></param>
        private void sayHello(string p_name, string p_some)
        {
            Console.WriteLine("{0}，你好。{1}", p_name, p_some);
        }

        /// <summary>
        /// 符合委托say的方法定义
        /// </summary>
        /// <param name="p_name"></param>
        /// <param name="p_some"></param>
        private void sayBye(string p_name, string p_some)
        {
            Console.WriteLine("{0}，再见。{1}", p_name, p_some);
        }

        /// <summary>
        /// 符合委托say的方法定义
        /// </summary>
        /// <param name="p_name"></param>
        /// <param name="p_some"></param>
        private void sayNothing(string p_name, string p_some)
        {
            Console.WriteLine("{0}，讲不出再见。{1}", p_name, p_some);
        }

        /// <summary>
        /// 委托多路广播1
        /// </summary>
        /// <param name="p_name">要对话的对象</param>
        public void seeOne(string p_name)
        {
            say nowDo = null;
            //这样写是错误的
            //nowDo = this.sayHello + this.sayBye;
            //这样写才是对的
            nowDo += this.sayHello;
            //取消未有的绑定是不会出错的
            nowDo -= this.sayBye;
            nowDo += this.sayBye;
            nowDo += this.sayNothing;
            //多播也可以取消绑定
            nowDo -= this.sayNothing;
            nowDo(p_name, "天气不错哦。");
        }

        /// <summary>
        /// 委托多路广播2
        /// </summary>
        /// <param name="p_name"></param>
        /// <param name="p_some"></param>
        public void seeOne(string p_name, string p_some)
        {
            say nowDo, nowDo1, nowDo2, nowDo3;
            nowDo1 = this.sayHello;
            nowDo2 = this.sayBye;
            nowDo3 = this.sayNothing;
            //这里可以这样写是因为两个都是委托实例而非方法实体
            nowDo = nowDo1 + nowDo2 + nowDo3;
            //照样可以取消绑定
            nowDo -= nowDo3;
            nowDo(p_name, p_some);
        }

        /// <summary>
        /// 委托匿名方法实现1
        /// </summary>
        public void seeMe()
        {
            new say(this.seeOne)("金展", "好好学习啊！~！") ;
        }

        /// <summary>
        /// 委托匿名方法实现2
        /// </summary>
        public void seeYou()
        {
            new say (
                delegate(string p_name, string p_some)
                {
                    Console.WriteLine("这是美好的一个晚上");
                    this.sayNothing(p_name, p_some);
                    this.sayBye(p_name, p_some);
                    this.sayHello(p_name, p_some);
                }
            )("厦门","现在天气很好哦！~");
        }

        /// <summary>
        /// 定义一个泛型方法，用于将两个参数组合
        /// </summary>
        /// <typeparam name="T">支持int、string等</typeparam>
        /// <param name="p_one">第一个参数</param>
        /// <param name="p_two">第二个参数</param>
        /// <returns></returns>
        public string getLink<T>(T p_one, T p_two)
        {
            return p_one.ToString() + p_two.ToString();
        }
    }
}
